import Food from '@modules/Food';
import ScorePanel from '@modules/ScorePanel';
import Snake from '@modules/Snake';
import GameControlConfig from '@config/GameControl';
import CommonConfig from '@config/Common';

// 游戏控制类
class GameControl {
    food: Food;                 // 食物的实例
    scorePanel: ScorePanel;     // 记分牌的实例
    snake: Snake;               // 蛇的实例
    direction: string;          // 蛇的方向
    isLive: boolean;            // 游戏是否结束

    constructor() {
        this.food = new Food();
        this.scorePanel = new ScorePanel();
        this.snake = new Snake();
        this.direction = '';
        this.isLive = true;
        this.init();
    }

    // 初始化
    init() {
        // 如果食物产生到了蛇的身体上，则重新产生食物
        this.checkFoodHitBody();
        // 绑定按钮事件
        document.addEventListener('keydown', this.keydownHandle);
        // 蛇的运动函数
        this.run();
    }

    // 按键按下的相应函数
    keydownHandle = (event: KeyboardEvent) => {
        if(/^(ArrowUp|Top|ArrowDown|Down|ArrowLeft|Left|ArrowRight|Right)$/.test(event.key)) {
            this.direction = event.key;
        }
    }

    // 蛇的运动函数
    run = () => {

        // 蛇当前的位置
        let X = this.snake.X;
        let Y = this.snake.Y;

        console.log(this.direction);
        // 根据方向控制蛇头的位置
        switch (this.direction) {
            // 向上运动
            case "ArrowUp":
            case "Top":
                Y -= CommonConfig.baseMove;
                break;
            // 向下运动
            case "ArrowDown":
            case "Down":
                Y += CommonConfig.baseMove;
                break;
            // 向左运动
            case "ArrowLeft":
            case "Left":
                X -= CommonConfig.baseMove;
                break;
            // 向右运动
            case "ArrowRight":
            case "Right":
                X += CommonConfig.baseMove;
                break;
        }

        //检查蛇头是否吃到食物
        this.checkEat(X, Y);

        try {
            // 更新蛇的当前位置
            this.snake.X = X;
            this.snake.Y = Y;
        } catch(e) {
            // 当撞墙时，游戏结束
            setTimeout(() => {
                if (e instanceof Error) {
                    alert(e.message + 'Game Over!!');
                }
            }, 50);
            this.isLive = false;
        }

        this.isLive && setTimeout(this.run, GameControlConfig.baseSpeed - (this.scorePanel.level - 1) * GameControlConfig.upSpeed);
    }

    // 检查蛇头是否吃到食物
    checkEat(X: number, Y: number) {
        if(X === this.food.X && Y === this.food.Y) {

            // 改变食物位置
            this.food.change();
            // 检查食物是否撞上身体，撞上就重新产生食物
            this.checkFoodHitBody();
            // 分数增加
            this.scorePanel.addScore();
            // 蛇的身体增长
            this.snake.addBody();
        }
    }

    checkFoodHitBody() {
        const bodies = this.snake.bodies;

        for(let i = 0; i < bodies.length; i++) {
            if(bodies[i].offsetTop === this.food.Y && bodies[i].offsetLeft === this.food.X) {
                this.food.change();
                this.checkFoodHitBody();
                break;
            }
        }
    }
}

export default GameControl;

